iT邦幫忙

2021 iThome 鐵人賽

DAY 24
0
Modern Web

Vue.js 進階心法系列 第 24

新增表單/編輯表單,共用?或分開?

  • 分享至 

  • xImage
  •  

目前我們寫好了一個新增的畫面

需求

接下來,常見的需求是,人員的新增之後是人員的編輯。

新增用的畫面

編輯用的畫面

假設編輯時,只能換頭貼,不能改名字的畫面

要合併表單的 component

我們的目的,是要將表單的 code 合成一個 compoennt ,讓 user 的資料都由這個表單來處理

一開始,還無法一步就做到這件事沒關係。只需要把握一個重點「不要加上不必要的 props」。

  • isEdit
  • useType: create, edit, read, manage-read, user-read....

這些加上的 props 都不好

先各別把 createUserForm 和 updateUserForm 做好

兩邊的 code 差別只差在一個 disabled

這簡單!用 isEdit 就可以搞定了 ← 這太「淺想」了。

上次有講過,表單是一種「寫入」資料的方式。
所以,依照「讀取」與「寫入」我們重新思考一下這個問題

# 新增 修改
avatar 讀/寫 讀/寫
name 讀/寫

如果要再追加一個需求,有一個帳號需要查看所有 user 的資料,但是不可以改

# 新增 修改 查看
avatar 讀/寫 讀/寫
name 讀/寫

這是不是 isEdit 就不行了?繼續看下去吧!

盤點一下 Vue 的讀與寫功能

#
component 外部使用(v-model) :value, checked @input, @change
component 設計 props event ($emit)
component 內 API $props/$attrs $listeners

所以?看得出怎麼做了嗎?

合併表單的程式碼

只需要在「唯讀的地方」,將「寫入的語法」拿掉。並且可以偵測拿掉,就可以了。
超級重要: ☆☆☆☆☆

使用 Vue3 時,因為 $listeners 沒有繼續存在,所以要用 $attrs
參考: $listeners removed

  • :disabled="!$listeners['update:name']"
  <form @submit.prevent="$emit('submit')">
    <p>
      <img :src="avatarSrc" alt=""><br />
      <input
        v-if="$listeners['update:file']"
        type="file"
        @change="$emit('update:file', $event.taget.files.item(0))">
    </p>
    <p><label>name: <br />
      <input
        type="text"
        :disabled="!$listeners['update:name']"
        :value="data.name"
        @input="$emit('update:name', {
          ...data,
          name: $event.target.value
        })"
      ></label>
    </p>
    <input type="submit" value="送出">
  </form>
export default {
  name: 'demo',
  props: {
    data: {
      type: Object,
      required: true,
    },
  },
  data(){
    return {
      new_avatar: null,
    }
  },
  computed: {
    avatarSrc() {
      return this.new_avatar || this.data.avatar;
    }
  },
};

而外部只要透過 @update:name="$store.commit('user', $event)" 就可以阻決定「要不要寫入資料」,配合 UserForm 是 pure component 若要改值,要將值傳出來並取代原本的物件。

若不改值就不用傳了,所以就不要掛上這個 event 就好啦!

src/views/UserCreate.vue

  <UserForm
    :file="$store.getters.file"
    @update:file="updateFile"
    :data="data"
    @update:name="$store.commit('user', $event)"
    @submit="onSubmit"
  ></UserForm>

src/views/UserEdit.vue

  <UserForm
    :file="$store.getters.file"
    @update:file="updateFile"
    :data="data"
    @submit="onSubmit"
  ></UserForm>

src/views/UserRead.vue

這樣一來,只要設定好,只有讀取的權限,只需要這樣使用,component 自己就應該知道如何切換讀寫權限了

  <UserForm :data="data"></UserForm>

終於有像樣一點的進階心法

這一步,才是剛開始進階!哈~~
前面是因為這樣的做法,是基於前述的小小習慣累積而來的

這個方法,在共用 form 表單時只要變更使用的方式,就可以改變畫面的讀寫形式。

優點

  • 可以應付各種讀寫變化的需求。
  • 表單變化,不用增加不必要的 props

上一篇
拆掉 v-model + computed get/set 到 vuex
下一篇
表單: 處理物件型資料的畫面
系列文
Vue.js 進階心法30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言